﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using interop;
namespace leodesigner
{
    public partial class SceneTreeView : WeifenLuo.WinFormsUI.Docking.DockContent
    {
        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam,
            int lParam);

        public SceneTreeView()
        {
            InitializeComponent();
            this.sceneTree.MouseWheel+= new System.Windows.Forms.MouseEventHandler(this.sceneTree_MouseWheel);
        }

        public CodersLab.Windows.Controls.TreeView Tree
        {
            get { return sceneTree; }
        }

        private void sceneTree_SelectionsChanged(object sender, EventArgs e)
        {
            designer.Designer.propertyview.Fill(sceneTree.SelectedNodes);
            designer.Designer.selectionChanged();
            interop.server.selection_changed(sceneTree.SelectedNodes);
        }

        private void newObjectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TypeSelector ts = new TypeSelector();
            if (ts.ShowDialog() == DialogResult.OK)
            {
                TreeNode parentNode;
                if (sceneTree.SelectedNodes.Count == 0)
                    parentNode = sceneTree.Nodes[0];
                else
                    parentNode = sceneTree.SelectedNodes[0];

                string type_name = ts.GetSelectedTypeName();
                if (type_name == null)
                    return;

                TreeNode newTreeNode = interop.server.new_entity(type_name,parentNode);

                if (newTreeNode != null)
                {
                    parentNode.Nodes.Add(newTreeNode);
                    parentNode.Expand();
                    //                    parentNode.Nodes.Insert(0, newTreeNode);
                    sceneTree.SelectedNodes.Clear();
                    sceneTree.SelectedNodes.Add(newTreeNode);
                }
            }


        }

        int compareTreeNodes(interop.EntityTreeNode s1, interop.EntityTreeNode s2)
		 {
			 int h1=s1.getElemHeight();
			 int h2=s2.getElemHeight();

			 return h2-h1;
		 }
        int compareTreeNodesReversed(interop.EntityTreeNode s1, interop.EntityTreeNode s2)
		 {
			 int h1=s1.getElemHeight();
			 int h2=s2.getElemHeight();

			 return h1-h2;
		 }


        private void deleteSelectedToolStripMenuItem_Click(object sender, EventArgs e)
        {
		if (sceneTree.Nodes.Count!=0 && sceneTree.SelectedNodes.Contains(sceneTree.Nodes[0]))
			return;

		if (sceneTree.SelectedNodes.Count==0)
			return;

		System.Windows.Forms.DialogResult res=MessageBox.Show("Biztos hogy torolni akarsz?","Delete",MessageBoxButtons.YesNo,MessageBoxIcon.Exclamation);

		if (res==System.Windows.Forms.DialogResult.No)
		{
			return;
		}

        List<interop.EntityTreeNode> l = new List<interop.EntityTreeNode>();

		foreach(TreeNode t in sceneTree.SelectedNodes)
            l.Add((interop.EntityTreeNode)t);


		l.Sort(compareTreeNodes);

        interop.server.delete_entities(l);

		this.sceneTree.SelectedNodes.Clear();
        designer.Designer.propertyview.Fill(sceneTree.SelectedNodes);
//		SEPEditorForm.mainForm.afterSelect(nullptr);
		return;

        }

        private void sceneTree_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("CodersLab.Windows.Controls.NodesCollection", false))
            {
                Point p = new Point(e.X, e.Y);
                Point pt = ((TreeView)(sender)).PointToClient(p);
                interop.EntityTreeNode DestinationNode = (interop.EntityTreeNode)((sender as TreeView).GetNodeAt(pt));
                if (DestinationNode == null)
                    return;

                //ugyis tudjuk, hogy a szelektalt node-okat akarjuk attenni jol
                //eloszor megnezzuk, hogy nem-e valami gyerekbe akarjuk rakni-e
                for (int n = 0; n < sceneTree.SelectedNodes.Count; ++n)
                {
                    TreeNode ptr;
                    for (ptr = DestinationNode; ptr!=null && ptr != sceneTree.SelectedNodes[n]; ptr = ptr.Parent) ;
                    if (ptr != null) //ha megtalaltuk egy oset, akkor kampec
                        return;

                }
                //ugy latszik minden franko;
                List<interop.EntityTreeNode> l = new List<interop.EntityTreeNode>();

                foreach (TreeNode t in sceneTree.SelectedNodes)
                    l.Add((interop.EntityTreeNode)t);

                l.Sort(compareTreeNodesReversed);

                
                interop.EntityTreeNode newParent=DestinationNode;
                for (int n=0; n<l.Count; ++n)
                {
                    interop.EntityTreeNode act=l[n] as interop.EntityTreeNode;
                    act.Remove();
                    DestinationNode.Nodes.Add(act);


//                    entity_t* e=act.m_Node;
//                    float4x4 wm=e.get_initial_world_matrix();
                    interop.Transform wm=act.GetInitialWorldMatrix();
//                    newParent.add_child(e);
                    newParent.AddChild(act);
//                    e.set_initial_world_matrix(wm);
                    act.SetInitialWorldMatrix(wm);
//                    e.on_change_property("initial_local_matrix");
                    act.OnChangeProperty("initiallocalmtx");
//                    ((float4x4prop)act.bag["initial_local_matrix"]).set(e.initial_local_matrix);
                    (act.bag["initiallocalmtx"] as interop.float4x4prop).set(act.GetInitialLocalMatrix());


                    if (newParent.IsActive() && !act.IsActive())
                        act.InitRecursive();
                    else	 if (!newParent.IsActive() && act.IsActive())
                        act.ExitRecursive();

                }
                        
                DestinationNode.Expand();
            }
        }

        private void sceneTree_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void sceneTree_DragOver(object sender, DragEventArgs e)
        {
			 const Single scrollRegion = 20;

			 // See where the cursor is
//			 Point p;//=Point(e.X,e.Y);

			 Point pt =  sceneTree.PointToClient(new Point(e.X,e.Y));

			 // See if we need to scroll up or down
			 if ((pt.Y + scrollRegion) > sceneTree.Height-sceneTree.ItemHeight)
			 {
				 // Call the API to scroll down
				 SendMessage(sceneTree.Handle, (int)277, (int)1, 0);
			 }
			 else if (pt.Y < (sceneTree.Top + scrollRegion))
			 {
				 // Call thje API to scroll up
				 SendMessage(sceneTree.Handle, (int)277, (int)0, 0);
			 }		 
        }

        private void sceneTree_ItemDrag(object sender, ItemDragEventArgs e)
        {
			 DoDragDrop(e.Item, DragDropEffects.Move);

        }
        private void sceneTree_MouseWheel(object sender, MouseEventArgs e)
        {
            if (sceneTree.SelectedNodes.Count==0)
                return;

            TreeNode parentNode=sceneTree.SelectedNodes[0].Parent;
            for (int n = 1; n < sceneTree.SelectedNodes.Count; ++n)
            {
                if (sceneTree.SelectedNodes[n].Parent!=parentNode)
                {
                    return;
                }
            }
            if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
            {
                List<interop.EntityTreeNode> l = new List<interop.EntityTreeNode>();
                foreach (TreeNode t in sceneTree.SelectedNodes)
                    l.Add((interop.EntityTreeNode)t);


                if (e.Delta < 0)
                {
                    l.Sort(compareTreeNodes);
                    if (l[0].NextNode == null)
                        return;
                }
                else
                {
                    l.Sort(compareTreeNodesReversed);
                    if (l[0].PrevNode == null)
                        return;
                }

                foreach (EntityTreeNode actNode in l)
                {
//                    EntityTreeNode actNode = sceneTree.SelectedNodes[0] as EntityTreeNode;
                    if (e.Delta > 0)
                    {
                        EntityTreeNode prevNode = actNode.PrevNode as EntityTreeNode;
                        if (prevNode != null)
                        {
                            prevNode.Remove();
                            actNode.Parent.Nodes.Insert(actNode.Index + 1, prevNode);
                            actNode.AddAfter(prevNode);
                            //                      sceneTree.SelectedNodes.Clear();
                            //                      sceneTree.SelectedNodes.Add(prevNode);
                        }
                    }
                    else
                    {
                        EntityTreeNode nextNode = actNode.NextNode as EntityTreeNode;
                        if (nextNode != null)
                        {
                            nextNode.Remove();
                            actNode.Parent.Nodes.Insert(actNode.Index, nextNode);
                            actNode.AddBefore(nextNode);
                            //                        sceneTree.SelectedNodes.Clear();
                            //                        sceneTree.SelectedNodes.Add(prevNode);
                        }
                    }
                }
            }
        }

        public void nodeNameChanged()
        {
            for (int n = 0; n < sceneTree.SelectedNodes.Count; ++n)
            {
                (sceneTree.SelectedNodes[n] as EntityTreeNode).setText();
            }
        }

		 EntityTreeNode CloneOne(EntityTreeNode toClone,EntityTreeNode parentNode)
		 {
			 EntityTreeNode newNode=toClone.clone(parentNode);
             server.CreatePropertyTable(newNode);

			 for (int n=0; n<toClone.Nodes.Count; ++n)
				 CloneOne(toClone.Nodes[n] as EntityTreeNode,newNode);
			 return newNode;

		 }


        private void cloneSelectedToolStripMenuItem_Click(object sender, EventArgs e)
        {
        if (sceneTree.Nodes.Count!=0 && sceneTree.SelectedNodes.Contains(sceneTree.Nodes[0]))
			        return;


		if (sceneTree.SelectedNodes.Count!=0)
		{
            List<EntityTreeNode> r = new List<EntityTreeNode>();
			for (int n=0; n<sceneTree.SelectedNodes.Count;++n)
			{
				TreeNode p=sceneTree.SelectedNodes[n].Parent;
				while (p!=null)
				{
					if (sceneTree.SelectedNodes.Contains(p))
						break;

					p=p.Parent;
				}

				if (p==null)
					r.Add((EntityTreeNode)sceneTree.SelectedNodes[n]);
			}

			List<EntityTreeNode> l=new List<EntityTreeNode>();

			r.Sort(new Comparison<EntityTreeNode>(compareTreeNodesReversed));

			for (int n=0; n<r.Count; ++n)
			{
				EntityTreeNode toClone=(EntityTreeNode)r[n];

				//				 SetChanged();

				l.Add(CloneOne(toClone,toClone.Parent as EntityTreeNode));
				bool parentActive=(toClone.Parent as EntityTreeNode).IsActive();

                if (parentActive)
                    l[n].InitRecursive();
			}
//			selectionChangedLock=true;
			sceneTree.SelectedNodes.Clear();
//			int count=l.Count;
			foreach (TreeNode t in l)
			{
//				count--;
/*
				if (!n)
					selectionChangedLock=false;
*/
				sceneTree.SelectedNodes.Add(t);
			}

			l[l.Count-1].EnsureVisible();

			return;
		}

		return;
        }
    }
}
